package com.bstek.code.service.templateservice.impl.crud1;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.apache.velocity.VelocityContext;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import com.bstek.code.dao.DBInfoDao;
import com.bstek.code.model.ColumnInfo;
import com.bstek.code.model.DisplayCols;
import com.bstek.code.model.Info;
import com.bstek.code.model.TableInfo;
import com.bstek.code.service.templateservice.ITempService;
import com.bstek.code.service.templateservice.TempServiceFactory;
import com.bstek.code.util.CodeUtil;
import com.bstek.code.util.JsonUtil;
import com.bstek.code.util.VelocityUtil;

/**
 * 单表维护实现类
 * 
 * @author xh_hanhw
 *
 */
@Service(OneTabCURDImpl.BEAN_ID)
public class OneTabCURDImpl implements ITempService {

	public static final String BEAN_ID = "ONETABCURDIMPL";
	
	@Resource(name = DBInfoDao.BEAN_ID)
	private DBInfoDao dBInfoDao;
	
	private Map<String,String> tempFiles = new HashMap<String, String>();
	
	public OneTabCURDImpl(){
		this.tempFiles.put("Entity", "/com/bstek/code/service/templateservice/impl/crud1/template/JAVABEAN.vm");
		this.tempFiles.put("Dao", "/com/bstek/code/service/templateservice/impl/crud1/template/DAO.vm");
		this.tempFiles.put("Service", "/com/bstek/code/service/templateservice/impl/crud1/template/SERVICE.vm");
		this.tempFiles.put("Controller", "/com/bstek/code/service/templateservice/impl/crud1/template/CONTROLLER.vm");
		this.tempFiles.put("View", "/com/bstek/code/service/templateservice/impl/crud1/template/CRUDForm.view.vm");
		this.tempFiles.put("Key", "/com/bstek/code/service/templateservice/impl/crud1/template/IDKEY.vm");
	}

	
	@Override
	public String create(Map<String,Object> parameter) throws Exception {
		String workSpaceSrc= (String) parameter.get("workSpaceSrc");
		String rootPkg= (String) parameter.get("rootPkg");
		String tabs= (String) parameter.get("tabs");
		String preBeanId = (String)parameter.get("preBeanId")==null?"":(String)parameter.get("preBeanId");
		String cols = (String)parameter.get("cols");
		validateParams(workSpaceSrc,rootPkg,tabs);
		//从数据库查询表信息
		List<TableInfo> tables=dBInfoDao.getTablesByNames(tabs);
		//初始化velocityContext
		VelocityContext context = VelocityUtil.initContext();
		//创建文件夹
		String pkgPath = createDir(workSpaceSrc, rootPkg);
		
		List<DisplayCols> displayCols = JsonUtil.jsonToList(cols, DisplayCols.class);
		
		//开始生成文件,并返回生成代码失败的表
		List<TableInfo> failTabs = new ArrayList<TableInfo>();
		int i = 0;
		for(TableInfo tab:tables){
			List<ColumnInfo> list = (List<ColumnInfo>) displayCols.get(i).getCols();
			i++;
			try{
				//context中放入模板填充信息
				context.put("info", getInfo(tab, rootPkg, preBeanId, list));
				create(context, tab, pkgPath);
				
			} catch(Exception e){
				e.printStackTrace();
				failTabs.add(tab);
			}
		}
		return generateMsg(failTabs);
	}
	
	
	@PostConstruct
	@Override
	public void putMap() {
		TempServiceFactory.putBean("1", this);
	}
	

	@Override
	public List<Map<String, Object>> generateMenuList(String workSpaceSrc,
			String pkgFilepath) {
		List<Map<String, Object>> dirs = new ArrayList<Map<String, Object>>();
		dirs.add(CodeUtil.generateMenu("entity",workSpaceSrc+"/"+pkgFilepath+"/entity","java实体类(ORM bean)"));
		dirs.add(CodeUtil.generateMenu("dao",workSpaceSrc+"/"+pkgFilepath+"/dao","数据库访问层"));
		dirs.add(CodeUtil.generateMenu("service",workSpaceSrc+"/"+pkgFilepath+"/service","服务层"));
		dirs.add(CodeUtil.generateMenu("controller",workSpaceSrc+"/"+pkgFilepath+"/view/{funName}","控制层"));
		dirs.add(CodeUtil.generateMenu("view",workSpaceSrc+"/"+pkgFilepath+"/view/{funName}","视图层"));
		return dirs;
	}
	

	@Override
	public List<Map<String, Object>> generateFileNames(String tabs,
			String filePath, String type) {
		List<Map<String, Object>> dirs = new ArrayList<Map<String, Object>>();
		String[] t = tabs.split(",");
		for (int i = 0; i < t.length; i++) {
			if("entity".equals(type)){
				dirs.add(CodeUtil.generaeFileName(type, filePath, t[i], CodeUtil.getEntityName(t[i])+".java"));
			}
			if("dao".equals(type)){
				dirs.add(CodeUtil.generaeFileName(type, filePath, t[i], CodeUtil.getEntityName(t[i])+"Dao.java"));
			}
			if("service".equals(type)){
				dirs.add(CodeUtil.generaeFileName(type, filePath, t[i], CodeUtil.getEntityName(t[i])+"Service.java"));
			}
			if("controller".equals(type)){
				dirs.add(CodeUtil.generaeFileName(type, filePath, t[i], CodeUtil.getEntityName(t[i])+"Controller.java"));
			}
			if("view".equals(type)){
				dirs.add(CodeUtil.generaeFileName(type, filePath, t[i], CodeUtil.getEntityName(t[i])+".view.xml"));
			}
		}
		return dirs;
	}
	
	/**
	 * 
	 * @description 校验参数
	 * @author zhangkun
	 * @date 2020年5月25日
	 * @param workSpaceSrc
	 * @param rootPkg
	 * @param tabs
	 */
	private void validateParams(String workSpaceSrc , String rootPkg , String tabs){
		Assert.hasText(workSpaceSrc, "workSpaceSrc不能为空");
		Assert.hasText(rootPkg, "rootPkg不能为空");
		Assert.hasText(tabs, "tabs不能为空");
	}
	
	/**
	 * 
	 * @description 生成文件路径并创建文件夹
	 * @author zhangkun
	 * @date 2020年5月21日
	 * @param type tempFiles的key
	 * @param filePath 根路径
	 * @param javaBean
	 * @return 文件路径
	 */
	private String generateFilePath(String type,String filePath,String javaBean){
		
		String path = filePath + File.separator + type.toLowerCase();
		if("Key".equals(type)){
			path = filePath + File.separator + "entity";
		}
		if("View".equals(type) || "Controller".equals(type)){
			path = filePath + File.separator + "view" + File.separator + javaBean.toLowerCase();
		}
		
		mkdirs(path);
		return path;
		
	}
	
	/**
	 * 
	 * @description 根据路径构建目录
	 * @author zhangkun
	 * @date 2020年5月22日
	 * @param path
	 */
	private void mkdirs(String path) {
		File file = new File(path);
		if(!file.exists())file.mkdirs();
	}
	
	/**
	 * 
	 * @description 生成文件名
	 * @author zhangkun
	 * @date 2020年5月21日
	 * @param javaBean
	 * @param type tempFiles的key
	 * @return
	 */
	private String generateFileName(String javaBean,String type){
		if("View".equals(type))
			return javaBean + ".view.xml";
		
		if("Entity".equals(type))
			return javaBean + ".java";
		
		return javaBean + type + ".java";
	}
	
	/**
	 * 
	 * @description 根据跟路径和包名创建文件夹
	 * @author zhangkun
	 * @date 2020年5月21日
	 * @param workSpaceSrc
	 * @param rootPkg
	 * @return
	 */
	private String createDir(String workSpaceSrc, String rootPkg) {
		//检查或创建包根目录
		String pkgFilepath=StringUtils.replace(rootPkg, ".", "/");
		String pkgPath=workSpaceSrc+"/"+pkgFilepath;
		File pkgFile=new File(pkgPath);
		if(!pkgFile.exists()){
			//文件目录不存在，自动创建
			pkgFile.mkdirs();
		}
		return pkgPath;
	}
	
	/**
	 * @description 生成返回信息
	 * @author zhangkun
	 * @date 2020年5月21日
	 * @param failTabs
	 */
	private String generateMsg(List<TableInfo> failTabs) {
		
		if(failTabs.size() > 0){
			StringBuffer res = new StringBuffer();
			res.append("以下表对应代码未生成成功：");
			for (TableInfo tab : failTabs) {
				res.append(tab.getName());
			}
			return res.toString();
		}
		
		return "所选表对应代码生成成功";
	}
	
	/**
	 * 
	 * @description 单表生成代码
	 * @author zhangkun
	 * @date 2020年5月25日
	 * @param context
	 * @param tab
	 * @param filePath
	 * @throws Exception
	 */
	private void create(VelocityContext context, TableInfo tab, String filePath) throws Exception {
		String javaBean = tab.getjName();
		for(String key:tempFiles.keySet()){
			if("Key".equals(key) && tab.getuPrimaryKey().size() <= 1)
				continue;
			String fileName= generateFileName(javaBean,key);
			String path = generateFilePath(key,filePath,javaBean);
			VelocityUtil.generateFile(context, path + File.separator + fileName, tempFiles.get(key));
		}
	}
	
	/**
	 * 
	 * @description 获取模板的填充信息
	 * @author zhangkun
	 * @date 2020年6月1日
	 * @param tab
	 * @param rootPkg
	 * @param preBeanId
	 * @return
	 */
	private Info getInfo(TableInfo tab, String rootPkg, String preBeanId,List<ColumnInfo> displayCols){
		Info info = new Info(tab.getjName(), rootPkg);
		if (StringUtils.hasText(preBeanId)) {
			preBeanId += ".";
			info.setPrBeanId(preBeanId.toUpperCase());
		}
		info.setDisplayCols(displayCols);
		info.setControllerBeanId((preBeanId  + tab.getjName() + "Controller").toUpperCase());// 设置bo的beanId
		info.setDaoBeanId((preBeanId  + tab.getjName() + "Dao").toUpperCase());
		info.setServiceBeanId((preBeanId  + tab.getjName() + "Service").toUpperCase());
		info.setTab(tab);
		return info;
	}


}
